﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Home.ArtDB;


namespace Home.ArtDB.WinGui
{
    /// <summary>
    /// 
    /// </summary>
    public partial class FrmMain : Form
    {
        #region ColumnStyles

        internal static DataGridViewCellStyle COLUMNSTYLE_ALIGMENT_LEFT = new DataGridViewCellStyle();
        internal static DataGridViewCellStyle COLUMNSTYLE_ALIGMENT_RIGHT = new DataGridViewCellStyle();
        internal static DataGridViewCellStyle COLUMNSTYLE_ALIGMENT_CENTER = new DataGridViewCellStyle();
        internal static DataGridViewCellStyle COLUMNSTYLE_CURRENCY = new DataGridViewCellStyle();
        internal static DataGridViewCellStyle COLUMNSTYLE_DATE = new DataGridViewCellStyle();

        /* /// <summary>
         /// 
         /// </summary>
         /// <param name="cellstyle"></param>
         /// <returns></returns>
         public static DataGridViewCellStyle GetCellStyle(CGridColumn.GridCellStyle cellstyle)
         {
             switch (cellstyle)
             {
                 case CGridColumn.GridCellStyle.Center:
                     return COLUMNSTYLE_ALIGMENT_CENTER;
                 case CGridColumn.GridCellStyle.Currency:
                     return COLUMNSTYLE_CURRENCY;
                 case CGridColumn.GridCellStyle.Date:
                     return COLUMNSTYLE_DATE;
                 case CGridColumn.GridCellStyle.Left:
                     return COLUMNSTYLE_ALIGMENT_LEFT;
                 case CGridColumn.GridCellStyle.Right:
                     return COLUMNSTYLE_ALIGMENT_RIGHT;
             }
             return COLUMNSTYLE_ALIGMENT_LEFT;
         }
         */
        #endregion

        /// <summary></summary>
        private enum EAppState { None, Busy, Ready, Selecting }

        private const string ITEM_ALL = "<alle>";
        private const string STARTARG_FILE = "file";
        private const string STARTARG_ARTIST = "artist";

        /// <summary></summary>
        private EAppState AppState = EAppState.None;

        /// <summary></summary>
        private string _rootFolderPath = "";

        /// <summary></summary>
        private ArtFileCollectionFilter _filter = new ArtFileCollectionFilter();

        /// <summary></summary>
        ArtFileCollection artFileCollection = new ArtFileCollection();

        /// <summary></summary>
        private bool __changed = false;

        /// <summary></summary>
        private bool _changed
        {
            get { return __changed; }
            set
            {
                __changed = value;

                this.Text = string.Format("{0}: {1}{2}", this.Tag, (_loadedFile.Equals(string.Empty) ? "-" : Path.GetFileNameWithoutExtension(_loadedFile)), (__changed ? "*" : ""));
            }
        }

        #region PROPERTIES

        /// <summary></summary>
        private bool GenreSelected { get { return (gridGenre.SelectedRows.Count > 0); } }
        /// <summary></summary>
        private bool ArtistSelected { get { return (gridArtist.SelectedRows.Count > 0); } }
        /// <summary></summary>
        private bool AlbumSelected { get { return (gridAlbum.SelectedRows.Count > 0); } }
        /// <summary></summary>
        private bool TitleSelected { get { return (gridTitle.SelectedRows.Count > 0); } }

        /// <summary></summary>
        private List<string> SelectedGenres
        {
            get
            {
                List<string> selectedItems = new List<string>();
                foreach (DataGridViewRow row in gridGenre.SelectedRows)
                {
                    if (row.Cells[ArtFile.GENRE].Value != null)
                    {
                        string selectedItem = row.Cells[ArtFile.GENRE].Value.ToString();
                        if (selectedItem == ITEM_ALL)
                            selectedItem = "";
                        selectedItems.Add(selectedItem);
                    }
                }
                return selectedItems;
            }
        }

        /// <summary></summary>
        private List<string> SelectedArtists
        {
            get
            {
                List<string> selectedItems = new List<string>();
                foreach (DataGridViewRow row in gridArtist.SelectedRows)
                    selectedItems.Add(row.Cells[ArtFile.ARTIST].Value.ToString());
                return selectedItems;
            }
        }

        /// <summary></summary>
        private List<string> SelectedAlbums
        {
            get
            {
                List<string> selectedItems = new List<string>();
                foreach (DataGridViewRow row in gridAlbum.SelectedRows)
                    selectedItems.Add(row.Cells[ArtFile.ALBUM].Value.ToString());
                return selectedItems;
            }
        }

        /// <summary></summary>
        private List<string> SelectedTitles
        {
            get
            {
                List<string> selectedItems = new List<string>();
                foreach (DataGridViewRow row in gridTitle.SelectedRows)
                    selectedItems.Add(row.Cells[ArtFile.TITLE].Value.ToString());
                return selectedItems;
            }
        }

        #endregion PROPERTIES

        /// <summary></summary>
        private DataGridView _clickedGrid;

        /// <summary></summary>
        private string _loadedFile = "";

        /// <summary></summary>
        private List<string> TitleSelectedRowsFiles
        {
            get
            {
                return gridTitle.SelectedRows.Cast<DataGridViewRow>().Select(row => row.Cells[ArtFile.FILESCOUNT].ToolTipText).
                    Where(item => item != null).SelectMany(item => item.Split(new char[] { '#', ';' }, StringSplitOptions.RemoveEmptyEntries)).
                    Select(file => file.Trim(' ', '\n')).Where(file => !file.Equals(string.Empty)).ToList();
            }
        }

        /// <summary></summary>
        private string _errors = "";

        /// <summary>
        /// 
        /// </summary>
        public FrmMain()
        {
            InitializeComponent();

            artFileCollection.OnArtFileLoad += new EventHandler<ArtFileEventHandlerAargs>(artFileCollection_OnArtFileLoad);
            artFileCollection.OnAddNewArtFileToDB += new EventHandler<ArtFileEventHandlerAargs>(artFileCollection_OnAddNewArtFileToDB);
            artFileCollection.OnUpdateArtFileInDB += new EventHandler<ArtFileEventHandlerAargs>(artFileCollection_OnUpdateArtFileInDB);
            artFileCollection.OnArtFileError += new EventHandler<ArtFileEventHandlerAargs>(artFileCollection_OnArtFileError);

            //Genre
            int index = gridGenre.Columns.Add(ArtFile.GENRE, "Genre");
            gridGenre.Columns[index].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

            //Artist
            index = gridArtist.Columns.Add(ArtFile.ARTIST, "Artist");
            gridArtist.Columns[index].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

            //Album
            index = gridAlbum.Columns.Add(ArtFile.ALBUM, "Album");
            gridAlbum.Columns[index].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

            //Title
            index = gridTitle.Columns.Add(ArtFile.TRACK, "Nr.");
            gridTitle.Columns[index].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            gridTitle.Columns[index].ValueType = System.Type.GetType("System.Integer");
            gridTitle.Columns[index].Width = 30;

            index = gridTitle.Columns.Add(ArtFile.TITLE, "Titel");
            gridTitle.Columns[index].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            //gridTitle.Columns[index].Width = 100;

            index = gridTitle.Columns.Add(ArtFile.COMMENT, "Kommentar");
            //gridTitle.Columns[index].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            gridTitle.Columns[index].Visible = false;

            index = gridTitle.Columns.Add(ArtFile.FILESCOUNT, "Dateien");
            gridTitle.Columns[index].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            gridTitle.Columns[index].Width = 45;

            index = gridTitle.Columns.Add(ArtFile.DURATION, "Spielzeit");
            gridTitle.Columns[index].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            gridTitle.Columns[index].Width = 75;


            index = gridTitle.Columns.Add(ArtFile.FILENAME, "Filename");
            gridTitle.Columns[index].Width = 45;
            gridTitle.Columns[index].Visible = false;

            index = gridTitle.Columns.Add(ArtFile.HOMEID, "HOMEID");
            gridTitle.Columns[index].Width = 45;
            gridTitle.Columns[index].Visible = false;

            index = gridTitle.Columns.Add(ArtFile.SIZE, "Grösse");
            //gridTitle.Columns[index].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            gridTitle.Columns[index].Visible = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_Load(object sender, EventArgs e)
        {
            StartArgs startArgs = new StartArgs(STARTARG_FILE);

            _rootFolderPath = Application.StartupPath;

            cbShowArtist.Items.Add(ArtFile.ARTIST);
            cbShowArtist.Items.Add(ArtFile.COMPOSER);
            string showArtist = startArgs.Get(STARTARG_ARTIST, ArtFile.ARTIST);
            if (showArtist.Equals(ArtFile.ARTIST, StringComparison.OrdinalIgnoreCase)) showArtist = ArtFile.ARTIST;
            else if (showArtist.Equals(ArtFile.COMPOSER, StringComparison.OrdinalIgnoreCase)) showArtist = ArtFile.COMPOSER;
            else showArtist = ArtFile.ARTIST;
            cbShowArtist.SelectedItem = showArtist;


            _loadedFile = (!startArgs.Get(STARTARG_FILE).Equals(string.Empty) && File.Exists(startArgs.Get(STARTARG_FILE))) ? startArgs.Get(STARTARG_FILE) : "";

            if (!_loadedFile.Equals(string.Empty) && artFileCollection.Open(_loadedFile))
            {
                SetAppState(EAppState.Busy);

                DataBind();

                _changed = false;

                SetAppState(EAppState.Ready);
            }
            else
            {
                btnOpen_Click(null, null);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void artFileCollection_OnUpdateArtFileInDB(object sender, ArtFileEventHandlerAargs e)
        {
            lblStatus.Text = string.Format("Datenbank aktualisieren... {0}/{1}", e.Index, e.Count);

            Application.DoEvents();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void artFileCollection_OnAddNewArtFileToDB(object sender, ArtFileEventHandlerAargs e)
        {
            lblStatus.Text = string.Format("Neue Dateien hinzufügen... {0}/{1}", e.Index, e.Count);

            Application.DoEvents();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void artFileCollection_OnArtFileLoad(object sender, ArtFileEventHandlerAargs e)
        {
            lblStatus.Text = string.Format("Dateien laden... {0}/{1}", e.Index, e.Count);

            Application.DoEvents();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void artFileCollection_OnArtFileError(object sender, ArtFileEventHandlerAargs e)
        {
            _errors += " - " + ((e.ArtFile != null) ? Path.GetFileName(e.ArtFile.FileName) : "Fehler") + Environment.NewLine;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void artFileCollection_OnFileFound(object sender, EventArgs e)
        {
            lblStatus.Text = sender.ToString();

            Application.DoEvents();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void artFileCollection_OnDataBinded(object sender, EventArgs e)
        {
            DataBind();

            SetAppState(EAppState.Ready);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="appstate"></param>
        private void SetAppState(EAppState appstate)
        {
            if (AppState == EAppState.Selecting || appstate == EAppState.Selecting)
            {
                AppState = appstate;
                return;
            }

            AppState = appstate;

            btnOpen.Enabled = false;
            mnuSave.Enabled = false;
            btnSave.Enabled = false;
            btnSaveAs.Enabled = false;
            btnSearch.Enabled = false;
            txtSearch.Enabled = false;

            gridAlbum.Enabled = false;
            gridArtist.Enabled = false;
            gridGenre.Enabled = false;
            gridTitle.Enabled = false;

            lblHinweis.Enabled = false;
            lblShowArtist.Enabled = false;
            cbShowArtist.Enabled = false;
            btnReset.Enabled = false;

            switch (appstate)
            {
                case EAppState.None:

                    btnOpen.Enabled = true;

                    lblStatus.Text = "Bereit";

                    break;

                case EAppState.Busy:

                    lblStatus.Text = "In Arbeit...";

                    break;

                case EAppState.Ready:

                    btnOpen.Enabled = true;
                    mnuSave.Enabled = true;
                    btnSave.Enabled = true;
                    btnSaveAs.Enabled = true;
                    btnSearch.Enabled = true;
                    txtSearch.Enabled = true;

                    gridAlbum.Enabled = true;
                    gridArtist.Enabled = true;
                    gridGenre.Enabled = true;
                    gridTitle.Enabled = true;

                    lblHinweis.Enabled = true;
                    lblShowArtist.Enabled = true;
                    cbShowArtist.Enabled = true;
                    btnReset.Enabled = true;


                    lblStatus.Text = "Bereit";

                    break;
            }

            Application.DoEvents();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (CheckChanged())
            {
                if (_loadedFile.Trim().Equals(string.Empty) || !Directory.Exists(Path.GetDirectoryName(_loadedFile)))
                {
                    openFileDialog.InitialDirectory = Application.StartupPath;
                }
                else
                {
                    openFileDialog.InitialDirectory = Path.GetDirectoryName(_loadedFile);
                }

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    _loadedFile = openFileDialog.FileName;

                    SetAppState(EAppState.Busy);

                    artFileCollection.Open(_loadedFile);

                    DataBind();

                    _changed = false;

                    SetAppState(EAppState.Ready);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>Weiter machen</returns>
        private bool CheckChanged()
        {
            if (_changed)
            {
                DialogResult dr = MessageBox.Show("Änderungen speichern?", "Änderungen", MessageBoxButtons.YesNoCancel);

                if (dr == DialogResult.Cancel) return false;

                if (dr == DialogResult.Yes)
                {
                    btnSave_Click(null, null);
                    while (_changed)
                    {
                        Thread.Sleep(1000);
                        Application.DoEvents();
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSaveAs_Click(object sender, EventArgs e)
        {
            if (_loadedFile.Trim().Equals(string.Empty) || !Directory.Exists(Path.GetDirectoryName(_loadedFile)))
            {
                saveFileDialog.InitialDirectory = Application.StartupPath;
            }
            else
            {
                saveFileDialog.InitialDirectory = Path.GetDirectoryName(_loadedFile);
            }

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                _loadedFile = saveFileDialog.FileName;

                SetAppState(EAppState.Busy);

                BackgroundWorker bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(bw_DoWorkSave);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerSaveCompleted);
                bw.RunWorkerAsync(_loadedFile);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (!_loadedFile.Trim().Equals(string.Empty) || Directory.Exists(Path.GetDirectoryName(_loadedFile)))
            {
                SetAppState(EAppState.Busy);

                BackgroundWorker bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(bw_DoWorkSave);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerSaveCompleted);
                bw.RunWorkerAsync(_loadedFile);
            }
            else
            {
                btnSaveAs_Click(sender, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_DoWorkSave(object sender, DoWorkEventArgs e)
        {
            string filename = e.Argument.ToString();

            artFileCollection.Save(filename);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_RunWorkerSaveCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            DataBind();

            _changed = false;

            SetAppState(EAppState.Ready);
        }

        /// <summary>
        /// 
        /// </summary>
        private void DataBind()
        {
            List<string> selectedGenres = gridGenre.SelectedRows.Cast<DataGridViewRow>().Select(row => row.Cells[ArtFile.GENRE].Value.ToString()).ToList();
            List<string> selectedArtists = gridArtist.SelectedRows.Cast<DataGridViewRow>().Select(row => row.Cells[ArtFile.ARTIST].Value.ToString()).ToList();
            List<string> selectedAlbum = gridAlbum.SelectedRows.Cast<DataGridViewRow>().Select(row => row.Cells[ArtFile.ALBUM].Value.ToString()).ToList();

            artFileCollection.SetFilter((_filter.Keys.Length > 0) ? _filter : null);

            gridGenre.Rows.Clear();
            List<string> genres = artFileCollection.GetGenreList();
            if (genres.Count > 1)
            {
                genres.Insert(0, ITEM_ALL);
            }

            foreach (string genre in genres)
            {
                DataGridViewRow row = new DataGridViewRow();
                row.CreateCells(gridGenre);
                int index = gridGenre.Rows.Add(row);
                gridGenre.Rows[index].Cells[ArtFile.GENRE].Value = genre;
            }

            gridGenre.Sort(new GridComparer(gridGenre.Columns[ArtFile.GENRE], ListSortDirection.Ascending));

            SelectItem(gridGenre, ArtFile.GENRE, selectedGenres);
            SelectItem(gridArtist, ArtFile.ARTIST, selectedArtists);
            SelectItem(gridAlbum, ArtFile.ALBUM, selectedAlbum);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="cellname"></param>
        /// <param name="selectedvalue"></param>
        private void SelectItem(DataGridView grid, string cellname, List<string> selectedvalues)
        {
            grid.ClearSelection();
            if (grid.Rows.Count > 0)
            {
                if (selectedvalues.Count == 0)
                    grid.Rows[0].Selected = true;
                else
                {
                    bool found = false;
                    foreach (DataGridViewRow row in grid.Rows)
                        foreach (string selectedvalue in selectedvalues)
                            if (row.Cells[cellname].Value.ToString() == selectedvalue)
                            {
                                row.Selected = true;
                                found = true;
                                if (!row.Displayed)
                                    grid.FirstDisplayedScrollingRowIndex = row.Index;
                                break;
                            }

                    if (!found)
                        grid.Rows[0].Selected = true;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridGenre_SelectionChanged(object sender, EventArgs e)
        {
            if (AppState == EAppState.Selecting)
                return;

            if (!GenreSelected)
                return;

            SetAppState(EAppState.Selecting);

            gridArtist.Rows.Clear();

            List<string> artists = new List<string>();
            foreach (string selectedGenres in SelectedGenres)
            {
                if (cbShowArtist.SelectedItem.ToString().Equals(ArtFile.ARTIST))
                {
                    artists.AddRange(artFileCollection.GetArtistList(selectedGenres));
                }
                else
                {
                    artists.AddRange(artFileCollection.GetComposerList(selectedGenres));
                }
            }

            foreach (string artist in artists)
            {
                DataGridViewRow row = new DataGridViewRow();
                row.CreateCells(gridArtist);
                int index = gridArtist.Rows.Add(row);
                gridArtist.Rows[index].Cells[ArtFile.ARTIST].Value = artist;
            }

            gridArtist.Sort(new GridComparer(gridArtist.Columns[ArtFile.ARTIST], ListSortDirection.Ascending));

            SetAppState(EAppState.Ready);

            SelectItem(gridArtist, ArtFile.ARTIST, _filter.SelectedArtists);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridArtist_SelectionChanged(object sender, EventArgs e)
        {
            if (AppState == EAppState.Selecting)
                return;

            if (!GenreSelected || !ArtistSelected)
                return;

            SetAppState(EAppState.Selecting);

            gridAlbum.Rows.Clear();

            List<string> albums = new List<string>();
            foreach (string selectedGenres in SelectedGenres)
            {
                foreach (string selectedArtist in SelectedArtists)
                {
                    albums.AddRange(artFileCollection.GetAlbumList(selectedGenres, selectedArtist, cbShowArtist.SelectedItem.ToString()));
                }
            }

            foreach (string album in albums)
            {
                DataGridViewRow row = new DataGridViewRow();
                row.CreateCells(gridAlbum);
                int index = gridAlbum.Rows.Add(row);
                gridAlbum.Rows[index].Cells[ArtFile.ALBUM].Value = album;
            }

            gridAlbum.Sort(new GridComparer(gridAlbum.Columns[ArtFile.ALBUM], ListSortDirection.Ascending));

            SetAppState(EAppState.Ready);

            SelectItem(gridAlbum, ArtFile.ALBUM, _filter.SelectedAlbums);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridAlbum_SelectionChanged(object sender, EventArgs e)
        {
            if (AppState == EAppState.Selecting)
                return;

            _filter.SelectedTitles.Clear();

            DataBindTitle();
        }

        /// <summary>
        /// 
        /// </summary>
        private void DataBindTitle()
        {
            if (!GenreSelected || !ArtistSelected || !AlbumSelected)
                return;

            SetAppState(EAppState.Selecting);

            gridTitle.Rows.Clear();

            DataTable titlesTbl = artFileCollection.NewTitleTable();
            foreach (string selectedGenres in SelectedGenres)
                foreach (string selectedArtist in SelectedArtists)
                    foreach (string selectedAlbum in SelectedAlbums)
                        foreach (DataRow row in artFileCollection.GetTitleTable(selectedGenres, selectedArtist, selectedAlbum, mnuGroup.Checked, cbShowArtist.SelectedItem.ToString()).Rows)
                            titlesTbl.ImportRow(row);

            foreach (DataRow row in titlesTbl.Rows)
            {
                DataGridViewRow newrow = new DataGridViewRow();
                newrow.CreateCells(gridTitle);
                int index = gridTitle.Rows.Add(newrow);

                gridTitle.Rows[index].Cells[ArtFile.TRACK].Value = Convert.ToInt32(row[ArtFile.TRACK]);
                gridTitle.Rows[index].Cells[ArtFile.TITLE].Value = row[ArtFile.TITLE].ToString();
                gridTitle.Rows[index].Cells[ArtFile.FILESCOUNT].Value = row[ArtFile.FILESCOUNT].ToString();
                gridTitle.Rows[index].Cells[ArtFile.SIZE].Value = row[ArtFile.SIZE];
                gridTitle.Rows[index].Cells[ArtFile.HOMEID].Value = row[ArtFile.HOMEID];

                TimeSpan ts = TimeSpan.FromMilliseconds((long)row[ArtFile.DURATION]);
                TimeSpan ts2 = new TimeSpan((int)ts.TotalHours, ts.Minutes, ts.Seconds);
                gridTitle.Rows[index].Cells[ArtFile.DURATION].Value = ts2.ToString("c");

                string files = (gridTitle.Rows[index].Cells[ArtFile.FILENAME].Value != null) ? gridTitle.Rows[index].Cells[ArtFile.FILENAME].Value.ToString() : "";
                foreach (string file in row[ArtFile.FILENAME].ToString().Split('#'))
                    files += file + "; ";
                if (files.Length < 3) files = "";
                gridTitle.Rows[index].Cells[ArtFile.FILESCOUNT].ToolTipText = files;

                string comments = (gridTitle.Rows[index].Cells[ArtFile.COMMENT].Value != null) ? gridTitle.Rows[index].Cells[ArtFile.COMMENT].Value.ToString() : "";
                foreach (string comment in row[ArtFile.COMMENT].ToString().Split('#'))
                    comments += comment + "; ";
                if (comments.Length < 3) comments = "";
                gridTitle.Rows[index].Cells[ArtFile.COMMENT].Value = comments;
            }

            gridTitle.Sort(new GridComparer(gridTitle.Columns[ArtFile.TRACK], ListSortDirection.Ascending));

            SetAppState(EAppState.Ready);

            SelectItem(gridTitle, ArtFile.TITLE, _filter.SelectedTitles);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSearch_Click(object sender, EventArgs e)
        {
            InitFilter();

            DataBind();
        }

        /// <summary>
        /// 
        /// </summary>
        private void InitFilter()
        {
            _filter.Keys = txtSearch.Text;

            if (GenreSelected)
                _filter.SelectedGenres = SelectedGenres;

            if (ArtistSelected)
                _filter.SelectedArtists = SelectedArtists;

            if (AlbumSelected)
                _filter.SelectedAlbums = SelectedAlbums;

            if (TitleSelected)
                _filter.SelectedTitles = SelectedTitles;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtSearch_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                btnSearch_Click(sender, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuOpenFolder_Click(object sender, EventArgs e)
        {
            List<string> errors = new List<string>();

            SetAppState(EAppState.Busy);

            SelectChildRows();

            TitleSelectedRowsFiles.Select(file => Path.GetDirectoryName(file)).Distinct().ToList().
               ForEach(dir => OpenDir(dir, errors));

            SetAppState(EAppState.Ready);

            if (!errors.Count.Equals(0))
                MessageBox.Show(errors.ToString("\n"));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="errors"></param>
        private void OpenDir(string dir, List<string> errors)
        {
            if (Directory.Exists(dir)) Process.Start(dir); else errors.Add(dir);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuDeleteRows_Click(object sender, EventArgs e)
        {
            SetAppState(EAppState.Busy);

            SelectChildRows();

            _changed = true;

            artFileCollection.RemoveFiles(TitleSelectedRowsFiles);

            DataBind();

            SetAppState(EAppState.Ready);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuSelectChilds_Click(object sender, EventArgs e)
        {
            SetAppState(EAppState.Busy);

            SelectChildRows();

            SetAppState(EAppState.Ready);
        }

        /// <summary>
        /// 
        /// </summary>
        private void SelectChildRows()
        {
            if (_clickedGrid.Equals(gridAlbum))
            {
                gridTitle.SelectAll();
                Application.DoEvents();
            }
            else if (_clickedGrid.Equals(gridArtist))
            {
                gridAlbum.SelectAll();
                Application.DoEvents();

                gridTitle.SelectAll();
                Application.DoEvents();
            }
            else if (_clickedGrid.Equals(gridGenre))
            {
                gridArtist.SelectAll();
                Application.DoEvents();

                gridAlbum.SelectAll();
                Application.DoEvents();

                gridTitle.SelectAll();
                Application.DoEvents();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridTitle_SelectionChanged(object sender, EventArgs e)
        {
            int hour = 0;
            int minu = 0;
            int sec = 0;
            long size = 0;
            foreach (DataGridViewRow row in gridTitle.SelectedRows)
            {
                object durObject = row.Cells[ArtFile.DURATION].Value;
                if (durObject != null)
                {
                    string[] durParts = durObject.ToString().Split(':');
                    hour += durParts[0].ToInt();
                    minu += durParts[1].ToInt();
                    sec += durParts[2].ToInt();
                }

                object sizeObject = row.Cells[ArtFile.SIZE].Value;
                if (sizeObject != null)
                {
                    size += sizeObject.ToLong();
                }

                TimeSpan ts = new TimeSpan((int)hour, minu, sec);
                lblPropertiesSelection.Text = "Größe: " + size.ToFormatDataSize() + "; Spielzeit: " + ts.ToString("c");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_DragDrop(object sender, DragEventArgs e)
        {
            List<string> dragdropList = ((string[])e.Data.GetData(DataFormats.FileDrop)).Cast<string>().ToList<string>();
            Dictionary<string, string> objectList = new Dictionary<string, string>();

            bool valid = true;
            foreach (string dragdropObject in dragdropList)
            {
                //Wenn Datei dann direkt hinzufügen
                if (File.Exists(dragdropObject))
                {
                    objectList.Add(dragdropObject, "file");
                }
                else
                //wenn Verzeichnis dann Verzeichnis hinzufügen
                {
                    string folder = dragdropObject;

                    //if (!Directory.Exists(folder))
                    //{
                    //    folder = Path.GetDirectoryName(folder);

                    //    if (!Directory.Exists(folder))
                    //    {
                    //        MessageBox.Show("Verzeichnis [" + dragdropObject + "] ist nicht gefunden.");
                    //        valid = false;
                    //        break;
                    //    }
                    //}

                    if (Directory.Exists(folder) && !objectList.ContainsValue(folder))
                    {
                        objectList.Add(folder, "folder");
                    }
                }
            }

            if (valid)
            {
                lblStatus.Text = "Verzeichnisse durchsuchen...";
                SetAppState(EAppState.Busy);

                BackgroundWorker bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                bw.RunWorkerAsync(objectList);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            Dictionary<string, string> objectList = (Dictionary<string, string>)e.Argument;

            List<string> files = objectList.Where(item => item.Value.Equals("folder")).SelectMany(item => Directory.EnumerateFiles(item.Key, "*.*", SearchOption.AllDirectories)).ToList();
            files.AddRange(objectList.Where(item => item.Value.Equals("file")).Select(item => item.Key));

            artFileCollection.AddFiles(files.Where(file =>
                file.EndsWith("mp3", StringComparison.OrdinalIgnoreCase) ||
                file.EndsWith("wma", StringComparison.OrdinalIgnoreCase) ||
                file.EndsWith("epub", StringComparison.OrdinalIgnoreCase)
            ).ToList());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            DataBind();

            _changed = true;

            if (!_errors.Equals(string.Empty))
            {
                FrmError frmError = new FrmError("Fehler beim Einlesen in folgenden Dateien:" + Environment.NewLine + _errors);
                frmError.Show();
                _errors = "";
            }

            SetAppState(EAppState.Ready);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cbList2Source_SelectedIndexChanged(object sender, EventArgs e)
        {
            gridArtist.Columns[ArtFile.ARTIST].HeaderText = cbShowArtist.SelectedItem.ToString();
            gridGenre_SelectionChanged(sender, e);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReset_Click(object sender, EventArgs e)
        {
            artFileCollection.Reset();

            gridAlbum.Rows.Clear();
            gridArtist.Rows.Clear();
            gridGenre.Rows.Clear();
            gridTitle.Rows.Clear();

            _changed = true;

            DataBind();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.S)
            {
                btnSave_Click(null, null);
            }
            else if (e.KeyCode == Keys.F5)
            {
                DataBind();
            }


        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void grid_MouseUp(object sender, MouseEventArgs e)
        {
            _clickedGrid = (DataGridView)sender;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!CheckChanged())
            {
                e.Cancel = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOverviewSaveAs_Click(object sender, EventArgs e)
        {
            if (createOverviewFileDialog.ShowDialog() == DialogResult.OK)
            {
                string overviewFile = createOverviewFileDialog.FileName;

                SetAppState(EAppState.Busy);

                BackgroundWorker bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(bw_DoWorkOverviewSave);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_DoWorkOverviewSaveCompleted);
                bw.RunWorkerAsync(overviewFile);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_DoWorkOverviewSave(object sender, DoWorkEventArgs e)
        {
            string filename = e.Argument.ToString();

            string result = artFileCollection.CreateOverviewPage(filename);

            if (result.Equals(string.Empty) && MessageBox.Show("Übersichts-Datei ist fertig. Verzeichnis öffnen?", "Fertig", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                SpecialFolder.ShowExplorerAtFile(filename);
            }
            else if (!result.Equals(string.Empty))
            {
                MessageBox.Show("Fehler beim Erstellen: " + result);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_DoWorkOverviewSaveCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            SetAppState(EAppState.Ready);
        }

    }

}